package com.ruoyi.client.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.ruoyi.client.mapper.ClientUserMapper;
import com.ruoyi.client.pojo.form.UserLoginForm;
import com.ruoyi.client.pojo.form.UserRegisterForm;
import com.ruoyi.client.pojo.form.UserUpdatePwdForm; // 引入修改密码表单
import com.ruoyi.client.pojo.vo.UserLoginVo;
import com.ruoyi.client.pojo.vo.UserRegisterVo;
import com.ruoyi.client.pojo.vo.UserVo;
import com.ruoyi.client.service.ClientUserService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.myshop.domain.ShopUser;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Author：HuaQP
 * @Date：2025/10/13
 */
@Service
public class ClientUserServiceImpl implements ClientUserService {

    @Resource
    ClientUserMapper clientUserMapper; //注入数据层Bean

    @Override
    public UserLoginVo login(UserLoginForm form) {
        ShopUser shopUser = clientUserMapper.selectByName(form.getName());
        if (shopUser == null) {
            throw new ServiceException("用户名不存在");
        }

        String passwordMd5 = Md5Utils.hash(form.getPassword() + shopUser.getSalt());
        if(passwordMd5.equals(shopUser.getPassword())){
            UserLoginVo userLoginVo = new UserLoginVo();
            BeanUtils.copyProperties(shopUser,userLoginVo);
            return userLoginVo;
        }
        throw new ServiceException("用户登录错误");
    }

    @Override
    public UserRegisterVo register(UserRegisterForm form) {
        ShopUser shopUser = clientUserMapper.selectByName(form.getName());
        if (shopUser != null) {
            throw new ServiceException("用户名已存在");
        }
        shopUser = new ShopUser();
        BeanUtils.copyProperties(form, shopUser);
        // 密码加密处理
        String salt = Md5Utils.hash(String.valueOf(System.currentTimeMillis()));//当前时间戳作为加密佐料
        String passwordMd5 = Md5Utils.hash(form.getPassword() + salt); //加密
        shopUser.setSalt(salt);
        shopUser.setPassword(passwordMd5);
        // 调用数据层,注册用户数据
        if (clientUserMapper.register(shopUser)) {
            UserRegisterVo userRegisterVo = new UserRegisterVo();
            BeanUtils.copyProperties(shopUser, userRegisterVo);
            return userRegisterVo;
        }
        throw new ServiceException("用户注册错误");
    }

    @Override
    public UserVo getMyDetail() {
        Long userId = StpUtil.getLoginIdAsLong(); // 获取当前登录用户的Id
        ShopUser shopUser = clientUserMapper.selectById(userId);
        if (shopUser == null) {
            throw new ServiceException("用户不存在");
        }
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(shopUser, userVo);
        return userVo;
    }

    @Override
    public void updatePassword(UserUpdatePwdForm form) {
        // 1. 校验新密码与确认密码一致性
        if (!form.getNewPassword().equals(form.getConfirmPassword())) {
            throw new ServiceException("新密码与确认密码不一致");
        }

        // 2. 获取当前登录用户ID（Sa-Token保证已登录，无需额外判空）
        Long userId = StpUtil.getLoginIdAsLong();

        // 3. 查询用户信息（含原密码和salt）
        ShopUser shopUser = clientUserMapper.selectById(userId);
        if (shopUser == null) {
            throw new ServiceException("用户不存在");
        }

        // 4. 校验原密码正确性（复用项目加密规则：Md5(原密码 + salt)）
        String oldPwdMd5 = Md5Utils.hash(form.getOldPassword() + shopUser.getSalt());
        if (!oldPwdMd5.equals(shopUser.getPassword())) {
            throw new ServiceException("原密码不正确");
        }

        // 5. 禁止新密码与原密码相同（增强安全性）
        if (form.getOldPassword().equals(form.getNewPassword())) {
            throw new ServiceException("新密码不能与原密码相同");
        }

        // 6. 加密新密码（复用原有salt，保持加密规则一致）
        String newPwdMd5 = Md5Utils.hash(form.getNewPassword() + shopUser.getSalt());
        shopUser.setPassword(newPwdMd5);

        // 7. 执行数据库更新
        int updateRows = clientUserMapper.updatePassword(shopUser);
        if (updateRows <= 0) {
            throw new ServiceException("密码修改失败，请重试");
        }

        // 8. 强制登出，要求用户重新登录（防止旧Token滥用）
        StpUtil.logout(userId);
    }
}